package model;

import java.awt.Point;
import java.util.Map;

import model.pieces.Piece;

/**
 * Interface to manage the pieces and the board
 */
public interface Model {
	
	/**
	 * Returns the board size
	 * @return board size
	 */
	public int getBoardSize();
	
	/**
	 * Clears the board from pieces- allocates a new chess board and clears piece maps
	 * for both players
	 */
	public void clearBoard();
	
	/**
	 * Returns the game board
	 * @return game board
	 */
	public Board getBoard();
	
	/**
	 * Places all 16 pieces on board (8 for each opponents).
	 * First player's pieces are placed at the upper part of the board (rows 7-8)
	 */
	public void setBoardStandard();
	
	/**
	 * Gets a position and checks if at least one of the row or column indices exceed board's size
	 * @param row- row index to check
	 * @param col- column index to check
	 * @return True if position does not fit on board, False if fits
	 */
	public boolean notValidPosition(int row, int col);
	
	/**
	 * Gets a position and checks if does not exceed board's size
	 * @param row- row index to check
	 * @param col- column index to check
	 * @return True if position does not fit on board, False if fits
	 */
	public boolean isValidPosition(int row, int col);
	
	/**
	 * Scans piece map of first player and checks if current piece is the King.
	 * Once the King is found, its position is returned.
	 * If first player does not hold a King, null is returned
	 * @return position of first player's King, or null if first player does not have a King
	 */
	public Point getFirstKingPosition();
	
	/**
	 * Scans piece map of second player and checks if current piece is the King.
	 * Once the King is found, its position is returned.
	 * If second player does not hold a King, null is returned
	 * @return position of second player's King, or null if second player does not have a King
	 */
	public Point getSecondKingPosition();
	
	/**
	 * Searches first player's King and returns it.
	 * If first player does not have a King, returns null
	 * @return reference to first player's King
	 */
	public Piece getFirstKing();
	
	/**
	 * Searches second player's King and returns it.
	 * If second player does not have a King, returns null
	 * @return reference to second player's King
	 */
	public Piece getSecondKing();

	/**
	 * Returns piece at given position. If position is not valid, returns null
	 * @param row- row index
	 * @param col- column index
	 * @return piece at given position or null if does not exist
	 */
	public Piece getPiece(int row, int col);
	
	/**
	 * Checks if indicated player has a piece at given position on board
	 * @param firstPlayer- indicates if piece assigned to first player or not 
	 * @param posToCheck- position where should check if piece is at
	 * @return True if indicated player has a piece at given position, False if not
	 */
	public boolean hasPiece(boolean firstPlayer, Point posToCheck);
	
	/**
	 * Moves piece at given source position to destination position, according to the indicated player.
	 * If there is no piece assigned to indicated player at source position, or destination is not a valid position,
	 * returns False. Otherwise, True	
	 * @param firstPlayer- indicates if should move a piece assigned to first player or not
	 * @param srcPosition- source position of piece
	 * @param destPosition- destination position of piece
	 * @return True if could move, False if not
	 */
	public boolean movePiece(boolean firstPlayer, Point srcPosition, Point destPosition);
	
	/**
	 * Return a map of first player's players- key is position and value is piece
	 * @return reference to first player's piece map
	 */
	public Map<Point, Piece> getFirstPlayerPieces();
	
	/**
	 * Return a map of second player's players- key is position and value is piece
	 * @return reference to second player's piece map
	 */
	public Map<Point, Piece> getSecondPlayerPieces();
	
	/**
	 * Adds to the board a piece of given type at given position. Updates given piece map with the new piece.
	 * If given type or position are invalid or there is another piece at given position, no piece is added and False is returned.
	 * Otherwise, adds the piece and returns True 
	 * @param position- position where to place the piece
	 * @param type- type of the new piece
	 * @param isFirstPlayer- indicates if should assign piece to first or second player
	 * @param playerPieces- pieces map of player that the new piece is assigned to
	 * @return True if could add a piece at given position, False if not
	 */
	public boolean addPiece(Point position, String type, boolean isFirstPlayer);
	
	/**
	 * Adds given piece at given position.
	 * If given position is not valid or there is another piece at given position,
	 * does not add the piece and False is returned. Otherwise, true is returned. 
	 * @param position- position of the new piece
	 * @param pieceToAdd- piece to be added
	 * @return True if could add piece, False if not
	 */
	public boolean addPiece(Point position, Piece pieceToAdd);
	
	/**
	 * Removes piece from given position
	 * @param position- position of the piece to remove
	 * @param isFirstPlayer- indicates if piece is assigned to first player
	 * @return True if could remove the piece, False if not
	 */
	public boolean removePiece(Point position, boolean isFirstPlayer);
	
	/**
	 * Checks if given piece is at board's end. Board's end is determined according to
	 * the player the piece is assigned to
	 * @param piece- piece to check
	 * @param position- position of the piece
	 * @return True if piece is at board's end, False if not
	 */
	public boolean isPieceAtEnd(Piece piece, Point position);	
}